import { instanceToPlain, plainToInstance } from 'class-transformer';
import {
  Controller,
  Get,
  Post,
  Body,
  Query,
  Put,
  Req,
  Param,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';

import { LoginDTO } from './dto/login.dto';
import { WechatInfoDTO } from './dto/wechatInfo.dto';
import { UpdateMiniuserDto } from './dto/update-miniuser.dto';
import { WxUserService } from './wxuser.service';
import { Public } from '../auth/auth.decorator';
import { Response } from '../../infra/schema/response';
import { WeChatService } from '../../infra/service/wechat.service';
import { WxUser } from './entities/wxuser.entity';
import { ApplyDoctorDto } from './dto/apply-doctor.dto';

@ApiTags('小程序用户')
@Controller('wxuser')
export class WxUserController {
  constructor(
    private readonly wxUserService: WxUserService,
    private readonly jwtService: JwtService,
  ) {}

  @Public()
  @Get('/getWechatInfo')
  @ApiOperation({ summary: '用户授权获取openid和session' })
  @ApiResponse({ type: Response<string> })
  async getWechatInfo(@Query() wechatInfoDTO: WechatInfoDTO) {
    console.log(wechatInfoDTO, 'codeeeeeeeeeeeeeeeeeeeee');

    return await WeChatService.getWechatInfo(wechatInfoDTO.code);
  }

  @Public()
  @Post('/login')
  @ApiOperation({ summary: '用户登录' })
  @ApiResponse({ type: Response<string> })
  async login(@Body() loginDTO: LoginDTO) {
    let user = await this.wxUserService.getUserByPhone(loginDTO.phone);
    if (!user) {
      user = plainToInstance(WxUser, {
        username: '用户' + new Date().getTime(),
        avatar: '',
        phone: loginDTO.phone,
      });

      await this.wxUserService.save(user);
    }

    const payload = instanceToPlain(user);
    const token = this.jwtService.sign(payload);

    const reponse = { user: payload, accessToken: token };
    return Response.success(reponse);
  }

  @Public()
  @Get(':userid')
  @ApiOperation({ summary: '通过用户id查询用户信息' })
  @ApiResponse({ type: Response<string> })
  async findOne(@Param('userid') userid: number): Promise<any> {
    // const userId = req.user.id;
    const userInfo = await this.wxUserService.getUserById(userid);
    return Response.success(userInfo);
  }

  @Public()
  @Post(':id')
  @ApiOperation({ summary: '修改用户信息' })
  @ApiResponse({ type: Response<string> })
  async updateUser(
    @Param('id') id: number,
    @Body() updateMiniuserDto: UpdateMiniuserDto,
  ): Promise<any> {
    const userId = id;
    const userUpdate = plainToInstance(WxUser, updateMiniuserDto, {
      exposeUnsetFields: true,
    });
    userUpdate.id = userId;

    await this.wxUserService.updateUser(userUpdate);
    const result = instanceToPlain(WxUser);
    return Response.success(result);
  }

  @Public()
  @Get()
  @ApiOperation({ summary: '分页查询wx用户列表' })
  @ApiResponse({ type: [WxUser] })
  async getUser(
    @Query('page') page: number = 1,
    @Query('size') size: number = 10,
    @Query('username') username: string = '',
  ) {
    const query = { page, size, username };
    const result = await this.wxUserService.getWxUserByList(query);
    return Response.successList(result.data, result.total);
  }

  @Public()
  @Post(':userId/apply-doctor')
  @ApiOperation({ summary: '用户申请成为医生' })
  @ApiResponse({ status: 201, description: '申请提交成功，请等待审核' })
  async applyToBeDoctor(
    @Param('userId') userId: string,
    @Body() applyDoctorDto: ApplyDoctorDto,
  ) {
    return this.wxUserService.applyToBeDoctor(+userId, applyDoctorDto);
  }

  @Public()
  @Put('approve-doctor/:doctorId')
  @ApiOperation({ summary: '后台审核通过医生申请' })
  @ApiResponse({ status: 200, description: '医生审核通过' })
  async approveDoctor(@Param('doctorId') doctorId: string) {
    await this.wxUserService.approveDoctor(+doctorId);
    return Response.success({ message: '医生审核通过' });
  }

  @Public()
  @Put('reject-doctor/:doctorId')
  @ApiOperation({ summary: '后台拒绝医生申请' })
  @ApiResponse({ status: 200, description: '医生审核拒绝' })
  async rejectDoctor(@Param('doctorId') doctorId: string) {
    await this.wxUserService.rejectDoctor(+doctorId);
    return Response.success();
  }
}
